package net.oschina.app.adapter;

import net.oschina.app.R;
import net.oschina.app.base.ListBaseAdapter;
import net.oschina.app.bean.Friend;
import net.oschina.app.widget.AvatarView;

import android.database.DataSetObserver;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.TextView;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import butterknife.ButterKnife;
import butterknife.InjectView;


public class FriendSelectAdapter extends ListBaseAdapter<Friend> {

    /**
     * 当选中一个{@link Friend friend}时，mFriendCheckStateMap.get(friend) == true;
     * 否则mFriendCheckStateMap.get(friend) == null
     */
    Map<Friend, Boolean> mFriendCheckStateMap = new HashMap<>();

    @Nullable
    OnCheckItemListener mOnCheckItemListener;

    public FriendSelectAdapter() {
        registerDataSetObserver(new DataSetObserver() {
            @Override
            public void onChanged() {
                // see http://stackoverflow.com/questions/1884889/iterating-over-and-removing-from-a-map
                final ArrayList<Friend> data = getData();
                final Iterator<Map.Entry<Friend, Boolean>> iterator =
                        mFriendCheckStateMap.entrySet().iterator();
                while (iterator.hasNext()) {
                    final Map.Entry<Friend, Boolean> next = iterator.next();
                    if (!data.contains(next.getKey())) {
                        iterator.remove();
                    }
                }
                // Use this↓ when we can use Java 1.8
                // mFriendCheckStateMap.entrySet().removeIf(e -> !data.contains(e.getKey()));
            }

            @Override
            public void onInvalidated() {
                mFriendCheckStateMap = new HashMap<>();
            }
        });
    }

    @Override
    protected View getRealView(int position, View convertView, final ViewGroup parent) {
        ViewHolder vh = null;
        if (convertView == null || convertView.getTag() == null) {
            convertView = getLayoutInflater(parent.getContext()).inflate(
                    R.layout.list_cell_friend_select, parent, false);
            vh = new ViewHolder(convertView);
            convertView.setTag(vh);
        } else {
            vh = (ViewHolder) convertView.getTag();
        }

        bindData(vh, mDatas.get(position));

        return convertView;
    }

    private void bindData(@NonNull final ViewHolder vh, @Nullable final Friend data) {
        if (data != null) {
            vh.name.setText(data.getName());

            vh.avatar.setAvatarUrl(data.getPortrait());
            vh.avatar.setUserInfo(data.getUserid(), data.getName());

            vh.checkbox.setChecked(hasCheck(data));
            vh.checkbox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
                @Override
                public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                    boolean allow = true;
                    if (mOnCheckItemListener != null) {
                        allow = mOnCheckItemListener.onCheckItem(
                                FriendSelectAdapter.this, data, vh, isChecked);
                    }
                    if (allow) {
                        if (isChecked) {
                            mFriendCheckStateMap.put(data, true);
                        } else {
                            mFriendCheckStateMap.remove(data);
                        }
                    } else {
                        //TODO Dialog?
                        buttonView.setChecked(!isChecked);
                    }
                }
            });
            vh.checkbox.setVisibility(View.VISIBLE);
        } else {
            vh.name.setText("");
            vh.avatar.setAvatarUrl(null);
            vh.avatar.setUserInfo(0, "");
            vh.checkbox.setVisibility(View.GONE);
            vh.checkbox.setOnCheckedChangeListener(null);
        }
    }

    public void setOnCheckItemListener(@Nullable OnCheckItemListener onCheckItemListener) {
        mOnCheckItemListener = onCheckItemListener;
    }

    public boolean hasCheck(@NonNull Friend friend) {
        final Boolean checked = mFriendCheckStateMap.get(friend);
        return checked != null && checked;
    }

    public int getCheckedItemsNumber() {
        return mFriendCheckStateMap.size();
    }


    public static class ViewHolder {

        @InjectView(R.id.tv_name)
        TextView name;

        @InjectView(R.id.checkbox)
        CheckBox checkbox;

        @InjectView(R.id.iv_avatar)
        AvatarView avatar;

        public ViewHolder(View view) {
            ButterKnife.inject(this, view);
        }
    }


    /**
     * 当列表项的选中状态要改变时被调用的Callback
     */
    public interface OnCheckItemListener {

        /**
         * 当列表项的选中状态要改变时被调用
         *
         * @param adapter   event source
         * @param friend    选中状态改变的项目
         * @param views     与此item绑定的视图
         * @param willCheck 要改变的（状态改变后的）选中状态
         * @return true：运行改变选中状态；false：拒绝改变选中状态
         */
        boolean onCheckItem(
                FriendSelectAdapter adapter, Friend friend, ViewHolder views, boolean willCheck);
    }

}
